package com.threeidiots.findit;

import java.util.Observable;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
/**
 * To get location
 * @author Hemslo
 *
 */
public class FindItLocation extends Observable {
	private LocationManager locationManager;
	private Location currentLocation;
	private LocationListener gpsListener;
	private LocationListener networkListner;
	
	public FindItLocation(Activity a) {
		locationManager = (LocationManager) a.getSystemService(Context.LOCATION_SERVICE);
	}
	
	public boolean isGPSon() {
		return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
	}
	
	public void GPSsetting() {
		
	}
	/**
	 * start listening to location updates
	 */
	public void start(){
        this.currentLocation = this.locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        Location tmp = this.locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if(this.isBetterLocation(tmp, this.currentLocation)) {
        	this.currentLocation = tmp;
        }
		gpsListener = new FindItLocationListner();
		networkListner = new FindItLocationListner();
		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, networkListner);
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, gpsListener);
	}
	
	/**
	 * stop all listeners
	 */
    public void stop() {
    	if (this.gpsListener != null) {
    		locationManager.removeUpdates(gpsListener);
    		this.gpsListener = null;
    	}
    	if (this.networkListner != null) {
    		locationManager.removeUpdates(networkListner);
    		this.networkListner = null;
    	}
    }
    
    public double getAccuracy() {
    	return this.currentLocation.getAccuracy();
    }
    
    public double getLatitude() {
    	return this.currentLocation.getLatitude();
    }
    
    public double getLongitude() {
    	return this.currentLocation.getLongitude();
    }
    
	private class FindItLocationListner implements LocationListener {

		public void onLocationChanged(Location location) {
			if (isBetterLocation(location, currentLocation)) {
				currentLocation = location;
				setChanged();
				notifyObservers();
			}

			// stop network listener
			if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
				locationManager.removeUpdates(this);
				networkListner = null;
			}
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

	}

	private static final int TWO_MINUTES = 1000 * 60 * 2;

	/**
	 * Determines whether one Location reading is better than the current
	 * Location fix
	 * 
	 * @param location
	 *            The new Location that you want to evaluate
	 * @param currentBestLocation
	 *            The current Location fix, to which you want to compare the new
	 *            one
	 */
	private boolean isBetterLocation(Location location,
			Location currentBestLocation) {
		if (location == null) {
			return false;
		}

		if (currentBestLocation == null) {
			// A new location is always better than no location
			return true;
		}

		// Check whether the new location fix is newer or older
		long timeDelta = location.getTime() - currentBestLocation.getTime();
		boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
		boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
		boolean isNewer = timeDelta > 0;

		// If it's been more than two minutes since the current location, use
		// the new location
		// because the user has likely moved
		if (isSignificantlyNewer) {
			return true;
			// If the new location is more than two minutes older, it must be
			// worse
		} else if (isSignificantlyOlder) {
			return false;
		}

		// Check whether the new location fix is more or less accurate
		int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
				.getAccuracy());
		boolean isLessAccurate = accuracyDelta > 0;
		boolean isMoreAccurate = accuracyDelta < 0;
		boolean isSignificantlyLessAccurate = accuracyDelta > 200;

		// Check if the old and new location are from the same provider
		boolean isFromSameProvider = isSameProvider(location.getProvider(),
				currentBestLocation.getProvider());

		// Determine location quality using a combination of timeliness and
		// accuracy
		if (isMoreAccurate) {
			return true;
		} else if (isNewer && !isLessAccurate) {
			return true;
		} else if (isNewer && !isSignificantlyLessAccurate
				&& isFromSameProvider) {
			return true;
		}
		return false;
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
		if (provider1 == null) {
			return provider2 == null;
		}
		return provider1.equals(provider2);
	}
}
